package com.eras.shoes.utils;

import android.annotation.SuppressLint;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import com.alibaba.fastjson.JSONObject;
import com.eras.shoes.application.MyApplication;
import com.eras.shoes.contents.BleBean;
import com.eras.shoes.contents.BleDataEx;
import com.eras.shoes.contents.Global;
import com.eras.shoes.contents.MessageCallBack;
import com.eras.shoes.contents.MessageEvent;
import com.eras.shoes.contents.SmartShoesWebBean;

import org.greenrobot.eventbus.EventBus;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BluetoothController {

    /**
     * 单例模式
     */
    private static volatile BluetoothController instance = null;
    private static BluetoothAdapter mBluetoothAdapter;
    private static BluetoothLeScanner bleScan;
    private String TAG = "BluetoothController";
//    public static String INSOLE_NAME = "INSOLE_DEVICE";
    public static String INSOLE_NAME_Shoes = "鞋";
    public static String INSOLE_NAME_Boot = "靴";
    public static String INSOLE_NAME_YK = "YK";
    private static ConcurrentHashMap<String, BleBean> mBluetoothDeviceMap = new ConcurrentHashMap<>();     //保存蓝牙设备信息,设备ID->设备信息
    private ConcurrentHashMap<String, BleBean> gattMap;
    public static String macAddress = null;
    public static String shoesName = "";
    public static String serialNumber = "";

    private BluetoothController() {
        gattMap = new ConcurrentHashMap<>();
    }
    public static BluetoothController getInstance() {
        if (instance == null) {
            synchronized (BluetoothController.class) {
                if (instance == null) {
                    instance = new BluetoothController();
                }
            }
        }
        return instance;
    }
//    Thread openBlueThread = new Thread(new Runnable() {
//        @SuppressLint("MissingPermission")
//        @Override
//        public void run() {
//            if (mBluetoothAdapter != null) {
//                mBluetoothAdapter.enable();
//            } else {
//                initBle();
//            }
//        }
//    });

    Thread closeBlueThread = new Thread(new Runnable() {
        @SuppressLint("MissingPermission")
        @Override
        public void run() {
            if (mBluetoothAdapter != null) {
                mBluetoothAdapter.disable();
            }
        }
    });

//    Thread initBlueThread = new Thread(() -> initBle());
    /**
     * 初始化蓝牙
     *
     * @return
     */
    @SuppressLint("MissingPermission")
    public void initBle(Context mContext) {
        BluetoothManager mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
        if (mBluetoothManager == null) {
            Toast.makeText(MyApplication.getInstance(), "您的手机不支持蓝牙",
                    Toast.LENGTH_SHORT).show();
            return;
        }
        mBluetoothAdapter = mBluetoothManager.getAdapter();  // 获取 BluetoothAdapter
        if (mBluetoothAdapter == null) {
            Toast.makeText(MyApplication.getInstance(), "您的手机不支持蓝牙",
                    Toast.LENGTH_SHORT).show();
            return;
        }
        if (!mBluetoothAdapter.isEnabled()) {
            mBluetoothAdapter.enable(); // 开启蓝牙
        }

    }
    /**
     * 重置蓝牙
     */
    @SuppressLint("MissingPermission")
    public void reInitBlue() {
        if (mBluetoothAdapter.isEnabled()) {  // 是为了清空已连接的蓝牙设备
            if (mBluetoothAdapter != null) {
                mBluetoothAdapter.disable();
            }
//            try {
//                closeBlueThread.start();
//                closeBlueThread.join();
//                openBlueThread.start();
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
        } else {
//            openBlueThread.start();  // 开启蓝牙
            if (mBluetoothAdapter != null) {
                mBluetoothAdapter.enable();
            } else {
//                initBle();
            }
        }
    }

    /**
     * 关闭蓝牙
     */
    @SuppressLint("MissingPermission")
    public void turnOffBluetooth() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (bluetoothAdapter != null) {
            if (bluetoothAdapter.isEnabled()) {
                bluetoothAdapter.disable();
            }
        }
    }

    /**
     * 开始扫描蓝牙
     */
    @SuppressLint("MissingPermission")
    public void startScanBle() {
        if (mBluetoothAdapter == null) {
//            initBlueThread.start();
            return;
        }
        bleScan = mBluetoothAdapter.getBluetoothLeScanner();
        if (bleScan == null) {
            return;
        }
        if (mBluetoothAdapter.isEnabled()) {
            bleScan.stopScan(scanCallback);
            bleScan.startScan(null, setScanSetting(), scanCallback);
        } else {
            Log.e(TAG, "蓝牙还未打开");
        }
    }

    private ScanSettings setScanSetting() {
        ScanSettings.Builder builder = new ScanSettings.Builder()
                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY);
        if (Build.VERSION.SDK_INT >= 23) {
            builder.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
            builder.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE);
        }

        return builder.build();
    }

    /**
     * 停止扫描蓝牙设备
     */
    @SuppressLint("MissingPermission")
    public void stopScanBle() {
        if (bleScan == null) {
            return;
        }
        if (mBluetoothAdapter.isEnabled()) {
            bleScan.stopScan(scanCallback);
        } else {
            Log.e(TAG, "蓝牙还未打开");
        }
    }

    /**
     * 是否蓝牙打开
     *
     * @return
     */
    public boolean isBleOpen() {
        if (mBluetoothAdapter != null) {
            return mBluetoothAdapter.isEnabled();
        }
        return false;
    }


    private ScanCallback scanCallback = new ScanCallback() {
        @Override
        public void onScanFailed(int errorCode) {
            super.onScanFailed(errorCode);
            Log.e(TAG, "扫描失败onScanFailed， errorCode==" + errorCode);
        }

        @Override
        public void onBatchScanResults(List<ScanResult> results) {
            super.onBatchScanResults(results);
            for (ScanResult scanResult : results) {
                Log.d(TAG, "批量扫描结果：" + scanResult.getDevice().getAddress());
            }
        }

        @Override
        @SuppressLint("MissingPermission")
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            String name = result.getDevice().getName();
            String address = result.getDevice().getAddress();
//            android.util.Log.d(TAG, "搜索到的设备：" + name + "  " + address + "  " + result.getRssi() + " " + result.getDevice().getBondState());

//            if(Global.connectedBluetoothMap.size() == 2){
//                stopScanBle();
//            }
            if (name != null) {  // 过滤搜索到的蓝牙设备
//                Log.e(TAG,"获取扫描信息："+ byteStr);
                if (name.contains(INSOLE_NAME_Shoes) || name.contains(INSOLE_NAME_Boot) || name.contains(INSOLE_NAME_YK)) {
//                    String serialNumber="";
                    Log.i(TAG, "设备=" + result);
                    Log.i(TAG, "设备ScanRecord=" + result.getScanRecord());
                    byte[] bytes = result.getScanRecord().getBytes();
                    Log.i(TAG, "设备ScanRecordbytes[]=" + ByteUtils.INSTANCE.bytesToHexString(bytes));
                    serialNumber = BleDataEx.getStringValue(bytes, 17, 9);
//                    if (!serialNumber.contains("YK")){//
//                        serialNumber = address;
//                    }
                    Log.i(TAG, "设备名称=" + name + " 序列号=" + serialNumber);
                    EventBus.getDefault().post(new MessageEvent<>(MessageEvent.BLE_SCAN_RESULT, result));
                }
            }
        }
    };

    /**
     * 连接到蓝牙设备
     *
     * @param address
     * @return
     */
    @SuppressLint("MissingPermission")
    public boolean connect(String address) {
        Global.connectState = 1;
        if (mBluetoothAdapter == null || TextUtils.isEmpty(address)) return false;

        //获取蓝牙设备
        BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) return false;

        // 如果设置自动连接，则安卓底层会不停的跟对应Mac地址的设备反复连接，连接效率会变得很慢，
        // 而且容易发送阻塞，导致后边的设备一直在等前一个设备连接成功的回调，蓝牙设备的连接一定要分开逐个连接，尽量不要形成线程阻碍。
        BluetoothGatt mBluetoothGatt = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            mBluetoothGatt = device.connectGatt(MyApplication.getInstance(), false, mBluetoothGattCallback, 2);
        } else {
            mBluetoothGatt = device.connectGatt(MyApplication.getInstance(), false, mBluetoothGattCallback);
        }
        if (mBluetoothGatt == null) {
            Log.e(TAG, "获取BLE蓝牙协议错误");
            return false;
        }

        return true;
    }



    /**
     * 与蓝牙通信回调
     */
    private BluetoothGattCallback mBluetoothGattCallback = new BluetoothGattCallback() {

        /**
         * 连接状态改变
         */
        @SuppressLint("MissingPermission")
        public void onConnectionStateChange(BluetoothGatt gatt, int oldStatus, int newStatus) {
            BluetoothDevice device = gatt.getDevice();
            Log.i("BluetoothController", "onConnectionStateChange 蓝牙状态输出: 新状态  "+newStatus+"   旧状态  "+oldStatus+"  BluetoothGatt  "+device.getName());
            if (newStatus == BluetoothGatt.STATE_CONNECTED && oldStatus == BluetoothGatt.GATT_SUCCESS) {  // 成功执行连接操作 && 设备已经连接
                Global.connectType = 1;
                Global.address = device.getAddress();
                Log.e("BluetoothController", "连接成功"+device.getName());
//                connectCount =1;
                String address = device.getAddress();
                macAddress = address;
//                if(device.getName().contains(INSOLE_NAME) || device.getName().contains(INSOLE_NAME_CN)){
//                    INSOLE_HERT_NAME = device.getName();
//                    //update by 20231218 叶凡宇 新增鞋垫产品
//                    Name_INSOLE = device.getName();
                    if(!mBluetoothDeviceMap.contains(address)) mBluetoothDeviceMap.put(address,new BleBean(gatt,device.getName(),address, 1));
//                    android.util.Log.i(TAG,"蓝牙状态输出:设备已连接,设置MTU[183],name[" + device.getName() + "]address[" + device.getAddress() + "]");
//                    //post消息
                    EventBus.getDefault().post(new MessageEvent<>(MessageEvent.ACTION_GATT_CONNECTED, new BleBean(device.getName(), address, 1)));
//                    EventBus.getDefault().post(new MessageEvent<>(MessageEvent.ACTION_CONNECTED, new BleBean(device.getName(), device.getAddress(), 1)));
//
//                    //设置MTU
                    gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
                    gatt.requestMtu(183);       //设置MTU
//                    //查找蓝牙可读写的服务，mtu设置完成后在发现服务
//
//                    int size = Global.connectedBluetoothMap.size();
//                    Global.connectedBluetoothMap.put(device.getAddress(),size);
////                    if(Global.connectedBluetoothMap.size() == 2){
//                stopScanBle();
////                    }
//                }
//
//                return;
//            }else {
//                gatt.disconnect();
//                gatt.close();
                if (!gattMap.containsKey(address)) {
                    gattMap.put(address, new BleBean(gatt, device.getName(), device.getAddress(), 1));
                }
            }
            if (newStatus == BluetoothGatt.STATE_DISCONNECTED) {  // 断开连接或未连接成功
                Log.e("BluetoothController", "连接断开"+device.getName());
                macAddress = null;
                Global.connectType = -1;
                Global.address = null;
                gattMap.clear();
                EventBus.getDefault().post(new MessageEvent<>(MessageEvent.ACTION_GATT_DISCONNECTED, device.getAddress()));
//                Log.i(TAG, "蓝牙状态输出: 断开了"+device.getName());
                closeGatt(gatt.getDevice().getAddress());
//                Global.connectedBluetoothMap.remove(gatt.getDevice().getAddress());   //关闭蓝牙时清理掉已经连接的蓝牙
                gatt.disconnect();
                gatt.close();
//                connectCount--;
//                if (connectCount < 0) {
                    disConnected(device);
//                    return;
//                }
//                if (Global.smartBluReCon) {
//                    connect(gatt.getDevice().getAddress());
//                    Log.i(TAG, "蓝牙状态输出: 开始重连" + device.getName());
//                }
            }
        }

        /**
         * 蓝牙断开连接
         * @param device
         */
        @SuppressLint("MissingPermission")
        private void disConnected(BluetoothDevice device) {
            String address = device.getAddress();
            if(mBluetoothDeviceMap.contains(address)){
                mBluetoothDeviceMap.get(address).getGatt().close();
                mBluetoothDeviceMap.remove(address);
            }
//            Global.TempConnectedAddress = Global.ConnectedAddress;
//            Global.isConnected = false;
////            Global.ConnectedAddress = null;
////            Global.ConnectedName = null;
//            Global.ConnectStatus = "unconnected";
//            closeBuletooth(device.getAddress());
//            Log.i(TAG, "蓝牙状态输出: 发送断开了信息"+device.getName());
            Log.e(TAG, "BluetoothConnectState: 定制鞋断开连接");
            EventBus.getDefault().post(new MessageEvent<>(MessageEvent.ACTION_GATT_DISCONNECTED, device.getAddress()));
//            EventBus.getDefault().post(new MessageEvent<>(MessageEvent.ACTION_UNCONNECTED_DIS, new BleBean(1, device.getName(), device.getAddress())));
        }

        private int LEFT_DATA_COUNTER = 0;
        private int RIGHT_DATE_COUNTER = 0;
        private long g_lPrintCount=0;
        /**
         *
         * @param gatt
         * @param characteristic
         */
        @SuppressLint("MissingPermission")
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override //, @NonNull byte[] value
        public void onCharacteristicChanged(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            BluetoothDevice device = gatt.getDevice();
            @SuppressLint("MissingPermission") String name = device.getName();
            int len = characteristic.getValue().length;
            byte[] dataBuffer = new byte[len];
            System.arraycopy(characteristic.getValue(),0,dataBuffer,0,len);
            if (checkBulCmdCode(device.getName(),dataBuffer)){
                Log.i(TAG,device.getName()+"：非实时数据=="+dataBuffer.toString());
                return;
            }else {
                if(g_lPrintCount++%10==0){
//                    Log.d(TAG, "onCharacteristicChanged name[" + device.getName() + "]address[" + device.getAddress() + "],数据内容:"+JSONObject.toJSON(dataBuffer));
                }
                Log.d(TAG, device.getName() + ",address:" + device.getAddress() + ",数据内容:"+ JSONObject.toJSON(dataBuffer));
//                Log.i(TAG, "设备数据内容=" + ByteUtils.INSTANCE.bytesToHexString(dataBuffer));
                String address=device.getAddress();
                onProcShoeData(name,address,dataBuffer);    //Bowen.hu20240815 直接处理蓝牙数据
            }

        }

        @RequiresApi(api = Build.VERSION_CODES.N)
        private void onProcShoeData(String deviceName, String address, byte[] dataBuffer){
            initParsing(dataBuffer,deviceName,address);
        }

        /**
         * 不转换网络字节序
         * @return
         */
        public boolean checkBulCmdCode(String name,byte[] dataBuffer){

            StringBuilder stringBuilder =new StringBuilder();
            for (int i = 0; i < dataBuffer.length; i++) {
                String hexString = Integer.toHexString(dataBuffer[i] & 0xFF);
                if (hexString.length() == 1){
                    stringBuilder.append("0");
                }
                stringBuilder.append(hexString);
            }
            //打印蓝牙传输过来的原始数据
//            if (name.contains("LEFT")) {
//                Log.i(TAG, "writeData 内容" + "\t"+stringBuilder);
//            }else {
//                Log.i(TAG, "writeData 右脚内容" + "\t"+stringBuilder);
//            }
            String substring = stringBuilder.toString().substring(8, 10);
//            Log.d(TAG,"writeData 接收指令回调: " + substring);
            if (!substring.equals("00")){
                String msg = "指令: ["+substring+"] 内容 :";
                MessageCallBack mes = new MessageCallBack();
                mes.cmd = substring;
                mes.status = true;
//                mes.msg = msg+stringBuilder.toString();
                mes.msg = stringBuilder.toString();
                Log.d(TAG,"writeData 接收指令回调: " + mes.msg);
                EventBus.getDefault().postSticky(new MessageEvent(MessageEvent.EVENT_DEVICE_COLL_BACK,JSONObject.toJSONString(mes)));
                return true;
            }
            return false;
        }

        /**
         * 读写characteristic时会调用到以下方法
         */
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic gattCharacteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                String result = bytes2HexString(gattCharacteristic.getValue());
                Log.i("test", "onReceive 接收到蓝牙: " + gatt.getDevice().getAddress() + " " + result);
//                EventBus.getDefault().postSticky(new MessageEvent(MessageEvent.ACTION_DATA_AVAILABLE, new BleBean(gatt.getDevice().getAddress(), gattCharacteristic.getValue())));
            }
        }

        /**
         * 写操作回调
         * @param gatt
         * @param characteristic
         * @param status
         */
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            String address = gatt.getDevice().getAddress();
            Log.d(TAG, "写操作回调： address: " + address + ",Write: " + bytes2HexString(characteristic.getValue()));
//            if (Global.isConnected && !Global.isStartReadData) {
//                synchronized (this) {
//                    Global.ReadCount = 0;
//                }
//            }
//            HermesEventBus.getDefault().post(new MessageEvent(MessageEvent.ACTION_GATT_WRITE_SUCCESS));
        }

        /**
         * 通知写入回调
         * @param gatt
         * @param descriptor
         * @param status
         */
        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorWrite(gatt, descriptor, status);
        }

        @SuppressLint("MissingPermission")
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor gattDescriptor, int status) {
            BluetoothDevice device = gatt.getDevice();
            if (status == BluetoothGatt.GATT_SUCCESS){
                Global.isConnected = true;
//                connectedTimestamp = System.currentTimeMillis();
                Log.e(TAG, "BluetoothConnectState: 定制鞋连接成功");
//                com.tencent.mars.xlog.Log.e(TAG, "蓝牙状态输出: 传输通道开启"+device.getName());
            }else {
                Log.e(TAG, "蓝牙状态输出: 传输通道开启失败 失败状态：" + status+"蓝牙名字 "+device.getName());
            }
//            lastTimestamp = 0;
//            EventBus.getDefault().post(new MessageEvent<>(MessageEvent.GATT_TRANSPORT_OPEN, status));
        }


        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onConnectionStateChange(gatt, status, status);
            Log.d(TAG, "onReadRemoteRssi： rssi: " + rssi + ",paramAnonymousInt2: " + status);
//            new Handler(Looper.getMainLooper()).postDelayed(
//                    () -> Log.d(TAG, "read rssi: " + gatt.readRemoteRssi()), 3000);
//            if (status == BluetoothGatt.GATT_SUCCESS){
//                synchronized (this){
//                    RSSI = rssi;
//                }
//            }
        }

        public void onReliableWriteCompleted(BluetoothGatt gatt, int paramAnonymousInt) {
        }

        /**
         * 成功发现设备的services时，调用此方法
         */
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {

            if (status == BluetoothGatt.GATT_SUCCESS){
                //update by 20231218 叶凡宇 新增鞋垫
                registerToBlueoothClient(gatt,true);
//                EventBus.getDefault().post(new MessageEvent<>(MessageEvent.GATT_TRANSPORT_OPEN, status));
            }
            else {
//                EventBus.getDefault().post(new MessageEvent<>(MessageEvent.GATT_TRANSPORT_OPEN, status));
            }


        }
        @SuppressLint("MissingPermission")
        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
            BluetoothDevice device = gatt.getDevice();
            android.util.Log.d(TAG, "MTU设置" + (BluetoothGatt.GATT_SUCCESS == status?"成功":"失败") + "，name[" + device.getName() + "]address[" + device.getAddress() + "]");
            if(BluetoothGatt.GATT_SUCCESS == status){
                gatt.discoverServices();    //发现服务
            }
        }
    };

    private UUID NEW_DESCRIPTOR_UUID= UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    private UUID NEW_SERVICE_UUID = UUID.fromString("000000ff-0000-1000-8000-00805f9b34fb");
    private UUID  NEW_READ_UUID= UUID.fromString("0000ff01-0000-1000-8000-00805f9b34fb");
    private UUID CCCD= UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    private UUID SERVICE_UUID= UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
    private UUID TX_CHAR_UUID= UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
    /**
     * 注册或者注销与蓝牙外设的实时数据读写
     * update by 20231218 叶凡宇
     * @param isEnable
     */
    @SuppressLint("MissingPermission")
    public void registerToBlueoothClient(BluetoothGatt gatt, boolean isEnable){
        BluetoothGattService service = gatt.getService(NEW_SERVICE_UUID);
        //List<BluetoothGattService> bluetoothGattServiceList = gatt.getServices();

        if(service == null){
            //update by 20231218 判断新老鞋子的蓝牙注册信息
            android.util.Log.e(TAG, "获取新GATT服务失败，获取老设备的SERVERID");
            enableTXNotification(true);
        } else {

            //获取特征码
            BluetoothGattCharacteristic characteristic = service.getCharacteristic(NEW_READ_UUID);
            if (characteristic == null) {
                android.util.Log.e(TAG, "获取GATT通道失败");
                clearBluetoothGatt(gatt.getDevice().getAddress());
                return;
            }

            gatt.setCharacteristicNotification(characteristic, isEnable);
            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(NEW_DESCRIPTOR_UUID);
            //开启或者关闭蓝牙数据通知
            descriptor.setValue(isEnable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
            //向蓝牙设备注册监听实现实时读取蓝牙设备的数据
            gatt.writeDescriptor(descriptor);
        }
    }

    /**
     * Enable TXNotification  与固件建立连接
     *
     * @return
     */
    @SuppressLint("MissingPermission")
    public void enableTXNotification(boolean isEnable) {
        for (String address : gattMap.keySet()) {
            BluetoothGatt gatt = gattMap.get(address).getGatt();
            BluetoothGattService RxService = gatt.getService(SERVICE_UUID);
            if (RxService == null) {
                closeGatt(address);
                return;
            }
            BluetoothGattCharacteristic TxChar = RxService.getCharacteristic(TX_CHAR_UUID);  // 获取特征码
            if (TxChar == null) {
                closeGatt(address);
                return;
            }

            boolean isEnableNotification = gatt.setCharacteristicNotification(TxChar, isEnable);
            BluetoothGattDescriptor descriptor = TxChar.getDescriptor(CCCD);
            if (isEnable) {
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            } else {
                descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
            }
            gatt.writeDescriptor(descriptor);  // 向蓝牙设备注册监听实现实时读取蓝牙设备的数据
        }
    }

    /**
     * 清理通讯协议
     * update by 20231218 叶凡宇
     *
     * @param address
     */
    @SuppressLint("MissingPermission")
    private void clearBluetoothGatt(String address){
//        Global.connectedBluetoothMap.remove(address);   //关闭蓝牙时清理掉已经连接的蓝牙
        if(mBluetoothDeviceMap.contains(address)){
            mBluetoothDeviceMap.get(address).getGatt().close();
            mBluetoothDeviceMap.remove(address);
        }
    }
    @SuppressLint("MissingPermission")
    public void closeGatt(String address) {
//        Global.connectedBluetoothMap.remove(address);   //关闭蓝牙时清理掉已经连接的蓝牙
//        if (gattMap.containsKey(address)) {
//            gattMap.get(address).getGatt().close();
//            gattMap.remove(address);
//            EventBus.getDefault().post(new MessageEvent<>(MessageEvent.ACTION_UNCONNECTED_DIS));
//            Global.isConnected = false;
//        }
        if(mBluetoothDeviceMap.contains(address)){
            mBluetoothDeviceMap.get(address).getGatt().disconnect();
            mBluetoothDeviceMap.get(address).getGatt().close();
            mBluetoothDeviceMap.remove(address);
            Global.address = null;
            EventBus.getDefault().post(new MessageEvent<>(MessageEvent.ACTION_GATT_DISCONNECTED, address));
        }


    }

    /**
     * 关闭连接
     * update by 20231221 叶凡宇
     *
     * @param address
     */
    @SuppressLint("MissingPermission")
    public void closeBuletooth(String address) {
//        Log.e("closeBuletooth","closeBuletooth="+address);
//        Log.e("closeBuletooth","mBluetoothDeviceMap="+mBluetoothDeviceMap);
        if (address == null) return;
        if (mBluetoothDeviceMap.containsKey(address)) {
            BluetoothGatt gatt = mBluetoothDeviceMap.get(address).getGatt();
            gatt.disconnect();
            gatt.close();
            mBluetoothDeviceMap.remove(address);
            Global.address = null;
            EventBus.getDefault().post(new MessageEvent<>(MessageEvent.ACTION_GATT_DISCONNECTED, address));
        }
    }

    public String writeData(String address, byte data, String number){
        String cmdCode = Integer.toHexString(data & 0xFF);
        String msg = "指令: ["+cmdCode+"] 内容 :";
        Log.e(TAG,"发送指令:" + msg);
        if(mBluetoothAdapter == null || TextUtils.isEmpty(address)) return msg;

        BleBean bleBean = mBluetoothDeviceMap.get(address);
        if (bleBean == null) return msg;
        Log.e(TAG,"发送指令，" + ",bleBean="+bleBean.toString());
        BluetoothGatt bluetoothGatt = bleBean.getGatt();
        List<BluetoothGattService> services = bluetoothGatt.getServices();
        Log.e(TAG,"发送指令，address:" + address + ",size="+services.size());
        if(services.size() < 3) {
            Log.e(TAG,"发送指令，address:" + address + ",没有找到适合的发送服务");
            return "";
        }

        List<BluetoothGattCharacteristic> characteristics = services.get(2).getCharacteristics(); //暂时使用第三个发送，前两个发送不成功
        BluetoothGattCharacteristic characteristic = characteristics.get(0);
//        List<String> numbers = toName(number);
//        byte[] serialNumber = new byte[numbers.size()];
//        for (int i = 0; i < numbers.size(); i++) {
//            Log.e("BluetoothController", "序列号="+numbers.get(i));
//            serialNumber[i] = HexConverter.INSTANCE.hexStringToByte(numbers.get(i));
//        }
//        byte[] serialNumber = hexString2Bytes(number);
        byte[] content;
        if (number.equals("")) {
            content = buildSendData(data, null, (short) 0);
        } else {
            byte[] serialNumbers = number.getBytes();
            Log.d(TAG, "writeData 发送指令 serialNumbers:" + serialNumbers.toString() + ",serialNumberSize:" + serialNumbers.length);
            content = buildSendData(data, serialNumbers, (short) serialNumbers.length);
        }
//        byte[] content = buildSendData(data, null, (short) 0);
        StringBuilder stringBuilder =new StringBuilder();
        for (int i = 0; i < content.length; i++) {
            String hexString = Integer.toHexString(content[i] & 0xFF);
            if (hexString.length() == 1){
                stringBuilder.append("0");
            }
            stringBuilder.append(hexString);
        }
        characteristic.setValue(content);
        @SuppressLint("MissingPermission") boolean status = bluetoothGatt.writeCharacteristic(characteristic);
        Log.e(TAG,"writeData 发送指令 address:" + address + ",status:" + status + ", data "+stringBuilder.toString());
        return msg+stringBuilder.toString();
    }
    /**
     *  cmd 命令，content 数据内容,dataLen为content数组的数据内容长度，content可以为null,为null时dataLen 必须为0
     */
    private byte[] buildSendData(byte cmd,byte[] content,short dataLen){
        short size = (short)(23 + dataLen); //从帧头到数据内容的数据大小
        byte[] data = new byte[size +2]; //加上最后校验码的2个字节
        short index = 0;
        //帧头
        data[index] = (byte)0x55;
        index++;
        data[index] = (byte)0xAA;
        index++;

        //数据大小，有效字节
        data[index] = (byte)(size-4 & 0x00ff);
        index++;
        data[index] = (byte)((size-4 >> 8) & 0x00ff);
        index++;


        //命令字
        data[index] = cmd;
        index++;

        //帧总数
        data[index] = 1;
        index++;
        data[index] = 0;
        index++;
        data[index] = 0;
        index ++;

        //第几帧
        data[index] = 0;
        index++;
        data[index] = 0;
        index++;
        data[index] = 0;
        index ++;

        long time = System.currentTimeMillis();
        byte[] timesData = getTimesData();
        Log.d(TAG,"writeData 发送指令 timesData:" + timesData.toString() + ",serialNumberSize:" + timesData.length);
        //时间戳
        data[index] = timesData[0];//(byte)((time >> 40) & 0xff);
        index++;
        data[index] = timesData[1];//(byte)((time >> 32) & 0xff);
        index++;
        data[index] = timesData[2];//(byte)((time >> 24) & 0xff);
        index++;
        data[index] = timesData[3];//(byte)((time >> 16) & 0xff);
        index++;
        data[index] = timesData[4];//(byte)((time >> 8) & 0xff);
        index++;
        data[index] = timesData[5];//(byte)(time  & 0xff);
        index++;
        //唯一标识时间戳
        data[index] = timesData[0];//(byte)((time >> 40) & 0xff);
        index++;
        data[index] = timesData[1];//(byte)((time >> 32) & 0xff);
        index++;
        data[index] = timesData[2];//(byte)((time >> 24) & 0xff);
        index++;
        data[index] = timesData[3];//(byte)((time >> 16) & 0xff);
        index++;
        data[index] = timesData[4];//(byte)((time >> 8) & 0xff);
        index++;
        data[index] = timesData[5];//(byte)(time  & 0xff);
        index++;

        //数据内容
        if(dataLen > 0 && content != null && content.length >= dataLen){
//            System.arraycopy(data,index,content,0,dataLen);
            for (int i = 0; i < content.length; i++) {
                data[index] = content[i];//(byte)(time  & 0xff);
                index++;
            }
        }

//        index += dataLen;
        short crc16 = (short)BleDataEx.crc16Modbus(data,(short)0,index);
        data[index] = (byte)((crc16 >> 8) & 0xff);
        index++;
        data[index] = (byte)(crc16  & 0xff);
        index++;

        return data;
    }

    private static final char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    public static String bytes2HexString(final byte[] bytes) {
        if (bytes == null) return "";
        int len = bytes.length;
        if (len <= 0) return "";
        char[] ret = new char[len << 1];
        for (int i = 0, j = 0; i < len; i++) {
            ret[j++] = hexDigits[bytes[i] >> 4 & 0x0f];
            ret[j++] = hexDigits[bytes[i] & 0x0f];
        }
        return new String(ret);
    }

    public static byte[] hexString2Bytes(String hexString) {
        if (isSpace(hexString)){
            return null;
        }
        int len = hexString.length();
        if (len % 2 != 0) {
            hexString = "0" + hexString;
            len = len + 1;
        }
        char[] hexBytes = hexString.toUpperCase().toCharArray();
        byte[] ret = new byte[len >> 1];
        for (int i = 0; i < len; i += 2) {
            ret[i >> 1] = (byte) (hex2Int(hexBytes[i]) << 4 | hex2Int(hexBytes[i + 1]));
        }
        return ret;
    }
    private static int hex2Int(final char hexChar) {
        if (hexChar >= '0' && hexChar <= '9') {
            return hexChar - '0';
        } else if (hexChar >= 'A' && hexChar <= 'F') {
            return hexChar - 'A' + 10;
        } else {
            throw new IllegalArgumentException();
        }
    }
    private static boolean isSpace(final String s) {
        if (s == null) return true;
        for (int i = 0, len = s.length(); i < len; ++i) {
            if (!Character.isWhitespace(s.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    // 16进制字符串转字节数组
    public static byte[] hexStringToBytes(String hexStr) {
        int len = hexStr.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4)
                    + Character.digit(hexStr.charAt(i+1), 16));
        }
        return data;
    }

    /**
     * 将字符串转换为16进制字节数组
     * @param input 输入字符串
     * @return 16进制表示的字节数组
     */
    public static byte[] stringToHexBytes(String input) {
        byte[] utf8Bytes = input.getBytes(StandardCharsets.UTF_8);
        byte[] hexBytes = new byte[utf8Bytes.length * 2];

        for (int i = 0; i < utf8Bytes.length; i++) {
            int v = utf8Bytes[i] & 0xFF;
            hexBytes[i * 2] = (byte) Character.toUpperCase(Character.forDigit((v >>> 4) & 0xF, 16));
            hexBytes[i * 2 + 1] = (byte) Character.toUpperCase(Character.forDigit(v & 0xF, 16));
        }
        return hexBytes;
    }

    /**
     * 将16进制字符串转换为byte[]
     *
     * @param str
     * @return
     */
    public static byte[] toBytes(String str) {
        byte[] bytes = new BigInteger(str, 16).toByteArray();
        return bytes;
    }
    public static List<String> toName(String name) {
        List<String> names = HexConverter.INSTANCE.convertHexString(name);
        return names;
    }

    public byte[] getTimesData(){
        long l = System.currentTimeMillis();
        String hexString = Long.toHexString(l);
        if (hexString.length()<12){
            hexString = "0"+hexString;
        }
        byte [] bytes = new byte[6];
        Pattern compile = Pattern.compile("..");
        Matcher matcher = compile.matcher(hexString);
        String  str = "";
        int index = 5;
        while (matcher.find()){
            bytes[index] = (byte) Integer.parseInt(matcher.group(),16);
            index--;
        }
        return bytes;
    }



    @RequiresApi(api = Build.VERSION_CODES.N)
    public void initParsing(byte[] data, String name, String address) {
        try {
            bluetoohNew(data,name,address);
        } catch (Exception e){
            Log.e(TAG, "initParsing: "+e);

        }
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public void bluetoohNew(byte[] data, String name, String address){
        try{

            int type;
            if (name.contains("LEFT") || name.contains("左")) {
                type = 0;
            } else if (name.contains("RIGHT") || name.contains("右")) {
                type = 1;
            } else {
                type = 2;
            }
//            Log.i(TAG, "initParsing: type"+type);
            //解析数据
            BleDataEx bleDataEx = new BleDataEx(name,address);
            try {
                bleDataEx.parseDataTypeTest(data, name);//此代码专为测试输出蓝牙数据
                //解析数据必须要try catch，否则异常向上抛出，可能会造成蓝牙处理问题 liujun 2024-07-27
                bleDataEx.parseData(data);
            }catch (Exception e){
                Log.w(TAG,e.getMessage());
                return;
            }
            BleDataEx.BleData bleData = bleDataEx.getDataList().get(0);
            List<Float> list = bleData.dataList;
//           Log.i(TAG, "bluetoohNew: 初始压力"+ JSONArray.toJSONString(list));
            //调用到显示界面
            // 目前默认是电量1个通道,
            // 10个压力通道,
            // 加速度3个通道、
            // 陀螺仪3个通道、
            // 地磁3个通道、
            // 温度1个通道、
            // 湿度1个通道，
            // 总共为22个通道。每个通道都是float型数据，也就是4个字节，大端模式。比如电量为90.1(0x42b43333)，实际发送的顺序是0x42、0xb4、0x33、0x33
            //温度
            int index = 0;
//        float electric = list.get(index++); //电量
            index += 10;//压力
            float[] speeds = new float[3];//加速度3个通道、
            speeds[0] = list.get(index++);
            speeds[1] = list.get(index++);
            speeds[2] = list.get(index++);
            index += 3; //陀螺仪3个通道、
            index += 3; //地磁3个通道、
            float electric = list.get(index++);//蓝牙剩余电量
            index++;//蓝牙状态
            index++;//蓝信号强度
            index +=3;
            index++;//压力
            float[] yalis = getWeight(list);
            getPressureMatrix(yalis, mCaclCount);

            mCaclCount++;
            float yal = 0;
            float yal1 = 0;
            if (mCaclCount <= maxLine) {
                if (mCaclCount == maxLine) {
                    Float[] resFloatArray = addOriginal();
                    mCaclCount--;
                    cleanList();
                }
                if (yaliSumArray.size() <= maxLine) {
//                    if (yaliSumArray.size() == maxLine) {
//                        Float[] array = yaliSumArray.toArray(yaliSumArrays);
//                        yaliAll = HttpProductData.findMedian(array);
//                    }
                    yaliSumArray.add(yal);
                } else {
                    yaliSumArray.remove(0);
                }
            }
//            sendEventBus(type == 1,bleData.uniqueTimestamp ,data);
            footHeatFirst(type, yalis, 0.0f, 0.0f,0.0f,name,yaliSumArray,bleData);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 获取压力
     * @param list
     * @return 20231219 yefanyu 新增鞋垫
     */
    private float[] getWeight(List<Float> list) {
        if (list.size() < 15) {
            return new float[10];
        }
        float[] yali = new float[10];
        for (int i = 0; i <= 9; i++) {
            yali[i] = list.get(i);
        }
        return yali;
    }

    /***
     * 清除第一个小标值
     */
    private void cleanList() {
        mPressureMatrixList0.remove(0);
        mPressureMatrixList1.remove(0);
        mPressureMatrixList2.remove(0);
        mPressureMatrixList3.remove(0);
        mPressureMatrixList4.remove(0);
        mPressureMatrixList5.remove(0);
        mPressureMatrixList6.remove(0);
        mPressureMatrixList7.remove(0);
        mPressureMatrixList8.remove(0);
        mPressureMatrixList9.remove(0);
    }
    /***
     * 每一片的压力值
     * @param yalis
     * @param calcCount
     */
    private void getPressureMatrix(float[] yalis, int calcCount) {
        if (calcCount < maxLine) {
            mPressureMatrixList0.add(yalis[0]);
            mPressureMatrixList1.add(yalis[1]);
            mPressureMatrixList2.add(yalis[2]);
            mPressureMatrixList3.add(yalis[3]);
            mPressureMatrixList4.add(yalis[4]);
            mPressureMatrixList5.add(yalis[5]);
            mPressureMatrixList6.add(yalis[6]);
            mPressureMatrixList7.add(yalis[7]);
            mPressureMatrixList8.add(yalis[8]);
            mPressureMatrixList9.add(yalis[9]);
        }
    }

    private  Float[] mOriginalArr = new Float[10];
    /***
     *二维数组列转行，并获取中间值
     * @return
     */
    private Float[] addOriginal() {
        Float[] mArray0 = (Float[]) mPressureMatrixList0.toArray(new Float[mPressureMatrixList0.size()]);
        Float[] mArray1 = (Float[]) mPressureMatrixList1.toArray(new Float[mPressureMatrixList1.size()]);
        Float[] mArray2 = (Float[]) mPressureMatrixList2.toArray(new Float[mPressureMatrixList2.size()]);
        Float[] mArray3 = (Float[]) mPressureMatrixList3.toArray(new Float[mPressureMatrixList3.size()]);
        Float[] mArray4 = (Float[]) mPressureMatrixList4.toArray(new Float[mPressureMatrixList4.size()]);
        Float[] mArray5 = (Float[]) mPressureMatrixList5.toArray(new Float[mPressureMatrixList5.size()]);
        Float[] mArray6 = (Float[]) mPressureMatrixList6.toArray(new Float[mPressureMatrixList6.size()]);
        Float[] mArray7 = (Float[]) mPressureMatrixList7.toArray(new Float[mPressureMatrixList7.size()]);
        Float[] mArray8 = (Float[]) mPressureMatrixList8.toArray(new Float[mPressureMatrixList8.size()]);
        Float[] mArray9 = (Float[]) mPressureMatrixList9.toArray(new Float[mPressureMatrixList9.size()]);
//        mOriginalArr[0] = HttpProductData.findMedian(mArray0);
//        mOriginalArr[1] = HttpProductData.findMedian(mArray1);
//        mOriginalArr[2] = HttpProductData.findMedian(mArray2);
//        mOriginalArr[3] = HttpProductData.findMedian(mArray3);
//        mOriginalArr[4] = HttpProductData.findMedian(mArray4);
//        mOriginalArr[5] = HttpProductData.findMedian(mArray5);
//        mOriginalArr[6] = HttpProductData.findMedian(mArray6);
//        mOriginalArr[7] = HttpProductData.findMedian(mArray7);
//        mOriginalArr[8] = HttpProductData.findMedian(mArray8);
//        mOriginalArr[9] = HttpProductData.findMedian(mArray9);

        return mOriginalArr;
    }

    public  List<Float> mPressureMatrixList0 = new ArrayList<>(); //每一片的压力矩阵
    public  List<Float> mPressureMatrixList1 = new ArrayList<>(); //每一片的压力矩阵
    public  List<Float> mPressureMatrixList2 = new ArrayList<>(); //每一片的压力矩阵
    public  List<Float> mPressureMatrixList3 = new ArrayList<>(); //每一片的压力矩阵
    public  List<Float> mPressureMatrixList4 = new ArrayList<>(); //每一片的压力矩阵
    public  List<Float> mPressureMatrixList5 = new ArrayList<>(); //每一片的压力矩阵
    public  List<Float> mPressureMatrixList6 = new ArrayList<>(); //每一片的压力矩阵
    public  List<Float> mPressureMatrixList7 = new ArrayList<>(); //每一片的压力矩阵
    public  List<Float> mPressureMatrixList8 = new ArrayList<>(); //每一片的压力矩阵
    public  List<Float> mPressureMatrixList9 = new ArrayList<>(); //每一片的压力矩阵
    private  int mCaclCount = 0;
    private  ArrayList<float[]> yaliList= new ArrayList<float[]>(); //存储每帧数
    private  ArrayList<Float> yaliSumArray = new ArrayList<Float>(); ; //存储每帧数的总负重数量
    private  int maxLine = 13;
    private  Float[] yaliSumArrays =  new Float[maxLine];
    private  SmartShoesWebBean smartShoesWebBean;



    /**
     * 发送数据
     *
     * @param type         类型 0左脚 1 右脚
     * @param vs           压力值数据集合
     * @param temperature  temperature 温度
     * @param humidity     湿度
     * @param electric     电量数据
     * @param name
     * @param yaliSumArray
     */
    @RequiresApi(api = Build.VERSION_CODES.N)
    private void footHeatFirst(int type, float[] vs, float temperature, float humidity, float electric, String name, ArrayList<Float> yaliSumArray,BleDataEx.BleData bulDate) {
        String data = "";
        if (type == 0) {
            data = vs[2] + "," + vs[1] + "," + vs[0] + "," + vs[3] + "," + vs[4] + "," + vs[5] + "," + vs[6] + "," + vs[7] + "," + vs[8] + "," + vs[9];
        } else {

            // [100,200,300]
            // data = vs[2] + "," +vs[1]+","+vs[0]+","+vs[5]+","+vs[4]+","+vs[3]+","+vs[7]+","+vs[6] +","+vs[9]+","+vs[8];
            data = vs[0] + "," + vs[1] + "," + vs[2] + "," + vs[3] + "," + vs[4] + "," + vs[5] + "," + vs[6] + "," + vs[7] + "," + vs[8] + "," + vs[9];
        }
        //Log.i(TAG, "footHeatFirst: 设备名: " +name+ " bulDate 数据 "+ JSONObject.toJSONString(bulDate.dataList));
        smartShoesWebBean = new SmartShoesWebBean();
        // todo 使用Handler 进行发送信息 获取对应鞋的数据
        smartShoesWebBean.setDataWebView("[" + data + "]");
        smartShoesWebBean.setElectric(electric);
        smartShoesWebBean.setTemperature(temperature);
        smartShoesWebBean.setHumidity(humidity);
        smartShoesWebBean.setType(type);
        smartShoesWebBean.setBleName(name);
        //和
        double sum = yaliSumArray.stream().mapToDouble(Float::floatValue).sum();
        smartShoesWebBean.setWeight(sum);
        smartShoesWebBean.setBulDate(bulDate);

        try {
            long l = System.currentTimeMillis();
            EventBus.getDefault().post(new MessageEvent<>(MessageEvent.SMART_SHOES_BLUETOOTH_DATA, smartShoesWebBean));
//            if (name.contains("LEFT") || name.contains("左")) {
//                Log.i(TAG, "footHeatFirst: left 数据 " + data);
//                EventBus.getDefault().post(new MessageEvent<>(MessageEvent.SMART_SHOES_BLUETOOTH_DATA_LEFT, smartShoesWebBean));
//            } else {
//                Log.i(TAG, "footHeatFirst: right 数据 " + data);
//                EventBus.getDefault().post(new MessageEvent<>(MessageEvent.SMART_SHOES_BLUETOOTH_DATA_RIGHT, smartShoesWebBean));
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
